package cc.siyecao.uid.zookeeper.resposity;

import cc.siyecao.uid.core.resposity.AssignerMode;
import cc.siyecao.uid.core.resposity.WorkerNodeResposity;
import cc.siyecao.uid.core.utils.StringUtils;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

/**
 * 配置
 *
 * @author lyt
 */
@Configuration
@Component
public class UidZkConfiguration {

    private static final String COUNTER_ZNODE = "/uid-generator/worker_node";

    @Value("${uid-generator.zookeeper.addrs:}")
    private String addrs;
    @Value("${uid-generator.zookeeper.authentication:}")
    private String authentication;
    @Value("${uid-generator.zookeeper.session-timeout-ms:15000}")
    private int sessionTimeoutMs;

    @Bean
    @Primary
    @ConditionalOnProperty(value = "uid-generator.assigner-mode", havingValue = AssignerMode.ZK)
    public WorkerNodeResposity workerNodeResposity() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry( 1000, 10 );
        CuratorFramework cf = null;
        if (StringUtils.isNotBlank( this.authentication )) {
            cf = CuratorFrameworkFactory.builder()
                    .connectString( this.addrs )
                    .sessionTimeoutMs( this.sessionTimeoutMs )
                    .retryPolicy( retryPolicy )
                    .authorization( "digest", this.authentication.getBytes() )
                    .build();
        } else {
            cf = CuratorFrameworkFactory.builder()
                    .connectString( this.addrs )
                    .sessionTimeoutMs( this.sessionTimeoutMs )
                    .retryPolicy( retryPolicy )
                    .build();
        }
        cf.start();
        DistributedAtomicLong distAtomicLong = new DistributedAtomicLong( cf, COUNTER_ZNODE, retryPolicy );
        return new WorkerNodeZK( distAtomicLong );
    }

}
